﻿/*! @file
********************************************************************************
<PRE>
文 件 名    : CSFile.cs
说    明    : 获取.CS的附属文件
作    者    : 汪泽然
--------------------------------------------------------------------------------
备    注    : 
--------------------------------------------------------------------------------
修改记录: 
 * 日    期    版  本    修改人    修改内容 
 * 2009-7-9    0.1.0     汪泽然    
</PRE>
********************************************************************************
* 版权所有(c) 2008 ~ 2009, 汪泽然, 保留所有权利
*******************************************************************************/
using System;
using System.IO;
using System.Xml;
using System.Xml.XPath;
using System.Collections.Generic;
using Wangzeran.Transform.Core.ITransform;
using System.Text.RegularExpressions;
using Wangzeran.Transform.Core.TransformException;

namespace Wangzeran.Transform.PlugIn.SubFiles
{
    /// <summary>
    /// 获取 CS文件
    /// </summary>
    public class CSFile : IChildFile
    {

        #region Common Variables

        /// <summary>
        /// 匹配文件夹
        /// </summary>
        private const string PATTERN_FOLDER = @".*\\";
        /// <summary>
        /// 匹配.cs文件
        /// </summary>
        private const string PATTERN_CSFILE = @".*cs\b";
        /// <summary>
        /// CSProj项目文件
        /// </summary>
        private const string TYPE_CSPROJ = @"csproj";
        /// <summary>
        /// CS文件
        /// </summary>
        private const string TYPE_CS = "*.cs";

        #endregion


        #region IGetSubFile 成员

        /// <summary>
        /// 获取 CS源代码文件
        /// </summary>
        /// <param name="filePath">项目文件路径</param>
        /// <param name="lstSubFiles">附属文件集合</param>
        /// <returns></returns>
        public bool GetChildFiles(string filePath, IList<string> lstSubFiles)
        {
            try
            {
                if (File.Exists(filePath))
                {
                    // 如果当前路径是文件，并且已存在
                    // 获取项目文件中的源代码文件列表
                    string fileName = "";
                    string path = Regex.Match(filePath, PATTERN_FOLDER, RegexOptions.IgnoreCase).ToString();

                    XmlDocument doc = new XmlDocument();
                    doc.Load(filePath);

                    XPathNavigator nav = doc.CreateNavigator();
                    XmlNamespaceManager manager = new XmlNamespaceManager(nav.NameTable);
                    manager.AddNamespace("ms", "http://schemas.microsoft.com/developer/msbuild/2003");

                    // 将迭代器指向Project/ItemGroup节点
                    XPathNodeIterator iter = nav.Select("/ms:Project/ms:ItemGroup", manager);
                    while (iter.MoveNext())
                    {
                        XPathNodeIterator newIter =
                            iter.Current.SelectDescendants(XPathNodeType.Element, false);

                        while (newIter.MoveNext())
                        {
                            if (newIter.Current.Name == "Compile")
                            {
                                // 获取当前节点的Include属性值，该属性值为源代码文件的相对路径 + 文件名
                                fileName = newIter.Current.GetAttribute("Include", 
                                    manager.DefaultNamespace);
                                if (fileName.Trim().Length != 0 &&
                                    Regex.IsMatch(fileName, PATTERN_CSFILE, RegexOptions.IgnoreCase))
                                {
                                    // 如果文件是.CS文件，则获取它的绝对路径，并加入附属文件集合
                                    lstSubFiles.Add(path + fileName);
                                }
                            }
                        }

                    }
                }
                else if(Directory.Exists(filePath))
                {
                    // 如果当前路径为目录，并且已经存在
                    // 则搜索该目录下的所有.cs文件，适用于WEB项目
                    string[] srcFiles = Directory.GetFiles(filePath, 
                            TYPE_CS, SearchOption.AllDirectories);

                    foreach (string item in srcFiles)
                    {
                        lstSubFiles.Add(item);
                    }
                }

                return true;
            }
            catch (Exception ex)
            {
                throw new UnGetSubFileException(filePath, ex.Message);
            }
        }

        #endregion
    }
}
